import hmac
import hashlib
import base64
import time
from dataclasses import dataclass

from test3 import settings

secret_key = None


@dataclass
class TokenAuthResult:
    Message: str  # 消息，用于返回验证结果信息
    Flag: bool  # 标志，验证是否通过
    User: int = None  # 用户ID，如果验证通过则包含此信息


class TokenAuth:
    TOKEN_VALIDITY_PERIOD = 7200  # Token有效时间设置为两个小时，用于实现无感刷新

    @staticmethod
    def make_user_token(uid):
        global secret_key
        """
        生成用户令牌
        """
        if secret_key is None:
            secret_key = "gzbwyvi75KWgqIKI0TlbAux8cRqezDikS3HYfcUI".encode('utf-8')

        # 当前时间戳
        timestamp = int(time.time())

        # 将用户 ID 和时间戳组装为消息
        message = f"{uid}:{timestamp}".encode('utf-8')
        token_hmac = hmac.new(secret_key, message, hashlib.sha256)

        # 编码消息和 HMAC 结果
        token_message = base64.urlsafe_b64encode(message).decode('utf-8')
        token_hash = base64.urlsafe_b64encode(token_hmac.digest()).decode('utf-8')

        # 返回以分隔符拼接的完整令牌
        token = f"{token_message}.{token_hash}"
        return token

    @staticmethod
    def valid_user_token(token):
        global secret_key

        """
        验证用户令牌
        """
        if secret_key is None:
            secret_key = "gzbwyvi75KWgqIKI0TlbAux8cRqezDikS3HYfcUI".encode('utf-8')
        if token == "debug" and settings.DEBUG:
            return TokenAuthResult("Debug模式", True, 1)
        try:
            # 分割令牌成消息部分和哈希部分
            token_message, token_hash = token.split('.')

            # 解码消息部分
            message = base64.urlsafe_b64decode(token_message.encode('utf-8')).decode('utf-8')
            token_uid, timestamp = message.split(':')

            # 转换时间戳
            timestamp = int(timestamp)
        except (ValueError, TypeError):
            return TokenAuthResult("验证不通过", False)  # 处理令牌格式错误

        # 检查时间戳是否在有效期内
        if time.time() - timestamp > TokenAuth.TOKEN_VALIDITY_PERIOD:
            return TokenAuthResult("Token过期了", False)

        # 重新生成 HMAC 并验证
        expected_hmac = hmac.new(secret_key, message.encode('utf-8'), hashlib.sha256)
        expected_hash = base64.urlsafe_b64encode(expected_hmac.digest()).decode('utf-8')

        if token_uid.isnumeric():
            token_uid = int(token_uid)

        if hmac.compare_digest(expected_hash, token_hash):
            # 验证通过，返回新的Token（实现无感刷新）
            return TokenAuthResult(TokenAuth.make_user_token(token_uid), True, token_uid)
        else:
            return TokenAuthResult("验证不通过", False)


if __name__ == '__main__':
    user_id = 2
    generated_token = TokenAuth.make_user_token(user_id)
    print(TokenAuth.valid_user_token(generated_token))
